﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Caching;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace RedisHelper.Config
{
   /// <summary>
    /// 缓存存储配置信息
    /// </summary>
    public class RedisBaseConfig {

        static ObjectCache cache = MemoryCache.Default;

        /// <summary>
        /// 根据键名获取缓存
        /// </summary>
        /// <param name="key">缓存键名</param>
        /// <returns></returns>
        static object GetCache(string key) {
            return cache[key];
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key">缓存键名</param>
        /// <param name="value">缓存键值</param>
        /// <param name="dependency">缓存依赖文件物理路径</param>
        static void SetCache(string key, object value, string dependencyFilePath) {
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string>() { dependencyFilePath }));
            cache.Set(key, value, policy);
        }

        /// <summary>
        /// 获取配置文件的服务器物理文件路径
        /// </summary>
        /// <typeparam name="T">配置信息类</typeparam>
        /// <returns>配置文件路径</returns>
        static string GetConfigPath<T>() {
            string path = AppDomain.CurrentDomain.BaseDirectory + "/";
            return path + typeof(T).Name + ".config";
        }

        /// <summary>
        /// 获取配置信息，首先从缓存中读取，如果读取失败则从配置文件中反序列化配置对象并写入缓存
        /// </summary>
        /// <typeparam name="T">配置信息类</typeparam>
        /// <param name="key">缓存键名</param>
        /// <returns>配置信息</returns>
        internal static T GetConfig<T>(string key) where T : class, new() {
            Type configClassType = typeof(T);
            object configObject = GetCache(key);
            if (configObject == null) {
                string configFilePath = GetConfigPath<T>();
                if (File.Exists(configFilePath)) {
                    using (var xmlTextReader = new XmlTextReader(configFilePath)) {
                        var xmlSerializer = new XmlSerializer(configClassType);
                        configObject = xmlSerializer.Deserialize(xmlTextReader);
                    }
                    SetCache(key, configObject, configFilePath);
                }
            }
            var config = configObject as T;
            if (config == null) {
                return new T();
            }
            return config;
        }
    }
}
